import type { AsyncData, UseFetchOptions } from "#app";

// 后台响应接口字段
export interface ResponseBody<T = any> {
  code: number;
  message: string;
  data: T;
  TotalCount: number;
}

export type RequestMethods = 'get' | 'post' | 'put' | 'delete';
export type TResponseType = 'basic' | 'cors' | 'error' | 'opaque' | 'opaqueredirect';
export type UseFetchOptionRewrite<T> = UseFetchOptions<ResponseBody<T>> & RequestConfigExtra;
export interface RequestConfigExtra {
  hasToken?: boolean;
  language?: string;
  backend?: boolean;
  interceptors?: {
    onRequest?: (config: any) => any;
    onResponse?: (res: any) => any;
  };
}

// 代理服务器前缀
// 延迟获取配置以避免在模块顶层调用 composable
function getProxyPrefix(): string {
  const config = useRuntimeConfig();
  return config.public.PROXY_PREFIX as string || '/server';
}

export class NuxtService {

  constructor (public timeout: number = 10000) {
    this.timeout = timeout;
  }

  request<R = any, T extends Record<string, any> = Record<string, any>>(
    url: string,
    method: RequestMethods,
    data?: T,
    options?: UseFetchOptionRewrite<R>,
  ): Promise<AsyncData<ResponseBody<R>, Error>> {
    return new Promise((resolve, reject) => {
      const fetchOptions: UseFetchOptionRewrite<R> = {
        timeout: this.timeout,
        hasToken: false, // 是否携带token
        backend: false, // 是否发送给独立服务器
        method,
        ...options, // 覆盖默认配置
        // 请求拦截器
        onRequest({ options: interceptorOptions }) {
          if (options?.hasToken) {
            interceptorOptions.headers.set(
              'Authorization',
              `Bearer 123`,
            );
          }
          if (options?.language) {
            interceptorOptions.headers.set('Accept-Language', options.language);
          }
          if (options?.interceptors?.onRequest) {
            options.interceptors.onRequest(interceptorOptions);
          }
        },
        // 响应拦截器
        onResponse({ response }) {
          if (options?.interceptors?.onResponse) {
            options.interceptors.onResponse(response);
          }
        },
        // useFetch是PromiseLike类型没有catch方法，只能通过回调去调用reject
        onResponseError({ error }) {
          reject(error);
        },
      };

      // 更具请求方法处理数据
      if (method === 'get') {
        fetchOptions.query = data;
      }
      else {
        fetchOptions.body = data;
      }
      // 处理代理请求的URL
      if (fetchOptions.backend) {
        // 如果是后端请求且URL不包含代理前缀，则添加代理前缀
        if (!url.startsWith(getProxyPrefix()) && !url.startsWith('http')) {
          url = `${getProxyPrefix()}${url.startsWith('/') ? url : `/${url}`}`;
        }
        // 清空baseURL以避免污染
        fetchOptions.baseURL = '';
      }
      // 如果需要携带token必须确保请求在客服端发起，否则无法获取token
      if (fetchOptions.hasToken) {
        fetchOptions.server = false; // 标记请求为客户端发起
      }
      useFetch<ResponseBody<R>>(url, fetchOptions as any).then((res) => {
        resolve(res as any);
      });
    });
  }

  get<R = any, T extends Record<string, any> = Record<string, any>>(
    url: string,
    query?: T,
    options?: Omit<UseFetchOptionRewrite<R>, 'onRequest' | 'onResponse'>,
  ) {
    return this.request<R>(url, 'get', query, options);
  }

  post<R = any, T extends Record<string, any> = Record<string, any>>(
    url: string,
    data?: T,
    options?: Omit<UseFetchOptionRewrite<R>, 'onRequest' | 'onResponse'>,
  ) {
    return this.request<R>(url, 'post', data, options);
  }

  put<R = any, T extends Record<string, any> = Record<string, any>>(
    url: string,
    data?: T,
    options?: Omit<UseFetchOptionRewrite<R>, 'onRequest' | 'onResponse'>,
  ) {
    return this.request<R>(url, 'put', data, options);
  }

  delete<R = any, T extends Record<string, any> = Record<string, any>>(
    url: string,
    data?: T,
    options?: Omit<UseFetchOptionRewrite<R>, 'onRequest' | 'onResponse'>,
  ) {
    return this.request(url, 'delete', data, options);
  }
}

export default new NuxtService();